package com.clt.ess.web;

import com.clt.ess.base.Constant;
import com.clt.ess.bean.ZTree;
import com.clt.ess.dao.IIssuerUnitDao;
import com.clt.ess.dao.ISealDao;
import com.clt.ess.entity.*;
import com.clt.ess.service.*;
import com.clt.ess.utils.FastJsonUtil;
import com.clt.ess.utils.PowerUtil;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.clt.ess.utils.Base64Utils.ESSGetBase64Decode;
import static com.clt.ess.utils.CertUtils.signCertByIssuerUnit;
import static com.clt.ess.utils.StringUtils.getRandom16;
import static com.clt.ess.utils.dateUtil.strToDate;
import static com.clt.ess.multica.crypt.MuticaCrypt.ESSGetBase64Encode;

@Controller
@RequestMapping("") // url:/模块/资源/{id}/细分 /seckill/list
public class MainController {

    protected HttpServletRequest request;
    protected HttpServletResponse response;
    protected HttpSession session;

    @Autowired
    private IUnitService unitService;
    @Autowired
    private IRoleAndPowerService roleAndPowerService;
    @Autowired
    private IIssuerUnitDao iIssuerUnitDao;
    @Autowired
    private ICertificateService certificateService;
    @Autowired
    private ISealService sealService;
    @Autowired
    private IErrorLogService errorLogService;
    @Autowired
    private IMainService mainService;
    @Autowired
    private ILogService logService;
    @Autowired
    private IUserService userService;
    @Autowired
    private AdminInfoService adminInfoService;
    @Autowired
    private ISealDao sealDao;
    @Autowired
    private PhoneLoginInfoService phoneLoginInfoService;
    /**
     * 每次拦截到请求会先访问此函数，
     * 获取request,session,response等实例
     * @param request http请求
     * @param response http回应
     */
    @ModelAttribute
    public void setReqAndRes(HttpServletRequest request, HttpServletResponse response){
        this.request = request;
        this.response = response;
        this.session = request.getSession();
    }


    /**
     * 验证签名信息
     * 2018.05.22
     * @return
     */
    @RequestMapping(value = "/essSealMake.html", method = RequestMethod.GET)
    public ModelAndView signatureTrack(String random){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("main");
        //判断随机数是否有参数传递过来
        if(random==null || "".equals(random)){
            modelAndView.setViewName("error");
            modelAndView.addObject("message", "参数信息被篡改，请重试！");
            return modelAndView;
        }

        //通过随机数查询用户信息
        PhoneLoginInfo info = phoneLoginInfoService.queryByRandom(random);
        if(info == null || info.getRandom()==null || "".equals(info.getRandom())){
            modelAndView.setViewName("error");
            modelAndView.addObject("message", "参数信息被篡改，请重试！");
            return modelAndView;
        }
        info.setRandom("");
        phoneLoginInfoService.updatePhoneLoginRandom(info);

        //根据personId查找用户表
        User user = new User();
        user.setPersonId(info.getPersonId());
        //状态有效的登录身份
        user.setState(Constant.STATE_YES);
        //查找符合条件的用户
        List<User> userList =  userService.findLoginUserByPersonId(user);
        if(userList.size()!=0 ){

            //将用户身份存入session，作为登录信息。
            session.setAttribute("user",userList.get(0));

            modelAndView.addObject("user", userList.get(0));

            modelAndView.addObject("userList", userList);

            //根据当前登录用户获取其单位列表结构
            List<ZTree> tree =  unitService.queryUnitMenu(userList.get(0).getUnitId());
            if(tree==null){
                errorLogService.addErrorLog("MainController-index-unitNameChain获取单位列表结构出错！");
                modelAndView.setViewName("error");
                modelAndView.addObject("message", "获取单位列表结构出错");
            }else{
                modelAndView.addObject("unit_menu", FastJsonUtil.toJSONString(tree));
            }
            //单位名称chain
            String unitNameChain = unitService.getUnitNameChain(userList.get(0).getUnitId());
            if("".equals(unitNameChain)||unitNameChain==null){
                errorLogService.addErrorLog("MainController-index-unitNameChain获取单位名称链出错！");
                modelAndView.setViewName("error");
                modelAndView.addObject("message", "获取单位名称链出错");
            }else{
                //放入当前单位名称chain，先清除。此处放入单位名称chain是为了写入系统日志是方便取用
                session.removeAttribute("unitNameChain");
                session.setAttribute("unitNameChain", unitNameChain);
            }
        }else{
            errorLogService.addErrorLog("MainController-index-userList根据personId查询的user为空！");
            modelAndView.setViewName("error");
        }
        return modelAndView;
    }

    /**
     * 获取跳转页面的随机数信息
     * @param personId
     * @return
     */
    @RequestMapping("/getJumpRandom.html")
    @ResponseBody
    public String getJumpRandom(String personId){
        if(personId == null || "".equals(personId)){
            return "error";
        }
        String str = getRandom16();
        PhoneLoginInfo info = new PhoneLoginInfo();
        info.setPersonId(personId);
        info.setRandom(str);
        Integer i = phoneLoginInfoService.updatePhoneLoginRandom(info);
        if(i==null || i<=0){
            return "error";
        }
        return str;
    }

    @RequestMapping(value = "/login.html", method = RequestMethod.POST)
    private ModelAndView login(String phone,String psw)  {
        //根据personId查找用户表
        User user = new User();
        user.setPersonId(phone);
        //状态有效的登录身份
        user.setState(Constant.STATE_YES);
        //查找符合条件的用户
        List<User> userList =  userService.findLoginUserByPersonId(user);

        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("/login.jsp");
        return modelAndView;
    }

    /**
     * 制章系统入口
//     * @param token 验证口令 网页访问PC客户端得到的令牌
     * @param userId 登录人ID可为空 在personId拥有多个登录身份时，在页面内切换身份时userId不为空
     * @return 视图信息
     */
    @RequestMapping(value = "/index.html", method = RequestMethod.GET)
    private ModelAndView index(String essPid,String userId)  {
        //视图对象
        return mainService.indexHandle(session,essPid,userId);

    }

    /**
     * 根据传入的单位ID 查询对应需要展示单位列表
     * @param unitId 单位ID
     * @return  zTree列表
     */
    @RequestMapping(value="/unit_menu.html", method = RequestMethod.GET,produces="text/html;charset=UTF-8")
    @ResponseBody
    public String unit_menu(String unitId){

        List<ZTree> tree =  unitService.queryUnitMenu(unitId);
        return FastJsonUtil.toJSONString(tree);
    }

    /**
     *根据印章ID查询印章状态并返回
     * @param sealId 印章ID
     * @return 印章状态
     */
    @RequestMapping(value="/querySealState.html", method = RequestMethod.GET)
    @ResponseBody
    public String querySealState(String sealId){
        int result;
        Seal seal = sealService.findSealById(sealId);
        result = seal.getSealState();
        return "ESSB"+String.valueOf(result)+"ESSE";
    }
    /**
     *客户端接口，临时使用
     * @param adminUK ukId
     */
    @RequestMapping(value="/queryAdminUK.html", method = RequestMethod.GET)
    @ResponseBody
    public String queryAdminUK(String adminUK){
        String result = sealDao.findAdminUK(adminUK);
        //传入的UKID如果存在的话，返回0，不准在返回1
        if(result==null){
            return "ESSB"+String.valueOf(1)+"ESSE";
        }else{
            return "ESSB"+String.valueOf(0)+"ESSE";
        }
    }

    /**
     * 日志接口，客户端下载印章完成
     * @param sealId 单位ID
     */
    @RequestMapping(value="/downloadComplete.html", method = RequestMethod.GET)
    @ResponseBody
    public String downloadComplete(String sealId)  {
        Seal seal = sealService.findSealById(sealId);
        logService.addSystemLog("制作了"+seal.getSealName(),"印章下载完成",
                seal.getUnitId(),"025user1","");
        return "ESSOK";
    }
    /**
     * 单位展示页默认页面
     */
    @RequestMapping(value="/unit_index.html", method = RequestMethod.GET)
    public ModelAndView unit_index() {
        //视图对象
        ModelAndView modelAndView = new ModelAndView();
        //设置返回视图
        modelAndView.setViewName("unit/showInfoPage");
        return modelAndView;
    }
    /**
     * 单位详情页面
     * @param toOpeUnitId 要打开的单位Id
     * @return s
     */
    @RequestMapping(value="/unit_page.html", method = RequestMethod.GET)
    public ModelAndView unit_page(String toOpeUnitId) {

        return mainService.initUnitPage(session,toOpeUnitId);
    }

    /**
     * 退出登录
     */
    @RequestMapping(value="/system_out.html", method = RequestMethod.GET)
    public ModelAndView system_out() {
        //删除session
        PowerUtil.delLoginUserFromSession(session);
        //TODO 网址替换为 管理系统的IP
        return new ModelAndView("redirect:https://10.1.10.34:8443/EssSealPlatform/unit/login");
    }
    /**
     * 对上传的证书进行签名
     * @param cert 证书cer文件
     * @param certId 证书ID
     * @throws IOException io异常
     */
    @RequestMapping(value="signCert.do", method = RequestMethod.POST)
    public void signCert(@RequestParam("cert") MultipartFile cert,String certId) throws IOException {
        //查询证书对象
        Certificate certificate = new Certificate();
        certificate.setCertificateId(certId);
        certificate.setState(1);
        List<Certificate> certificateList = certificateService.findCertificate(certificate);
        //要返回的证书文件二进制
        byte[] certByte = null;

        if(certificateList.get(0)!=null){
            // 判断文件是否为空
            if (!cert.isEmpty()) {
                try {
                    //得到证书信息对象
                    certificate = certificateList.get(0);
                    //证书颁发单位Id
                    String issuerUnitId = certificate.getIssuerUnitId();
                    //获取证书颁发单位
                    IssuerUnit issuerUnit = iIssuerUnitDao.findIssuerUnitById(issuerUnitId);

                    //算法
                    String algorithm = certificate.getAlgorithm();
                    //所在省份
                    String sS = certificate.getProvince();
                    //所在城市
                    String sL = certificate.getCity();
                    //单位
                    String sO = certificate.getCertUnit();
                    //部门
                    String sOU = certificate.getCertDepartment();
                    //公用名称
                    String sDN = certificate.getCerName();

                    //起始时间  当前时间减一天
                    Date dateStart = strToDate(certificate.getStartTime());
                    Date dateEnd  = strToDate(certificate.getEndTime());
                    //对上传的证书进行签名
                    certByte = signCertByIssuerUnit(cert.getBytes(),issuerUnit,sDN,sOU,sO,sL,sS,algorithm,dateStart,dateEnd);
                    //更新证书对象的证书数据
                    certificate.setCerBase64(ESSGetBase64Encode(certByte));
                    certificateService.updateCertificate(certificate);
                } catch (Exception e) {
                    e.printStackTrace();
                    errorLogService.addErrorLog("MainController-signCert-对上传证书进行签名时发生异常！");
                }
            }
        }

        if(certByte == null){
            //设置MIME类型
            response.setContentType("application/json");
            ServletOutputStream outputStream=response.getOutputStream();
            outputStream.write(("ESSNOO").getBytes());
            outputStream.close();
        }else{
            response.setContentType("application/json");
            ServletOutputStream outputStream=response.getOutputStream();
            String result = "ESSYES"+ESSGetBase64Encode(certByte)+"ESSEND";
            outputStream.write(result.getBytes());
            outputStream.close();
        }
    }

    /**
     *错误页面
     */
    @RequestMapping(value="error.html", method = RequestMethod.GET)
    public String error(Model model) {
        model.addAttribute("message",  "请登录安全客户端");
        return "error";
    }

    /**
     *下载附件
     * @param sealApplyId 申请信息Id
     */
    @RequestMapping(value="attachment.html", method = RequestMethod.GET)
    public void attachment(String sealApplyId) throws IOException {
        File file = null;
        SealApply sealApply = sealService.findSealApplyById(sealApplyId);
        if(sealApply==null){
            //设置MIME类型
            response.setContentType("application/json");
            ServletOutputStream outputStream=response.getOutputStream();
            outputStream.write(("error！").getBytes());
            outputStream.close();
        }else{
            file = new File(Constant.ATTACHMENT_PATH+sealApply.getAttachment());
            //设置MIME类型
            response.setContentType("application/octet-stream");
            //或者为response.setContentType("application/x-msdownload");
            //设置头信息,设置文件下载时的默认文件名，同时解决中文名乱码问题
            response.addHeader("Content-disposition", "attachment;filename="+new String(sealApply.getAttachment().getBytes(),
                    StandardCharsets.ISO_8859_1));

            InputStream inputStream=new FileInputStream(file);
            ServletOutputStream outputStream=response.getOutputStream();
            byte[] bs=new byte[1024];
            while((inputStream.read(bs)>0)){
                outputStream.write(bs);
            }
            outputStream.close();
            inputStream.close();
        }

    }
    /**
     *下载附件
     * @param certBase64 申请信息Id
     */
    @RequestMapping(value="downLoadCert.html", method = RequestMethod.GET)
    public void downLoadCert(String certBase64) throws IOException {


        byte [] certByte = ESSGetBase64Decode(certBase64);

        InputStream input = new ByteArrayInputStream(certByte);

        //设置MIME类型
        response.setContentType("application/octet-stream");
        //或者为response.setContentType("application/x-msdownload");
        //设置头信息,设置文件下载时的默认文件名，同时解决中文名乱码问题
        response.addHeader("Content-disposition", "attachment;filename="+new String("demo.cer".getBytes(),
                StandardCharsets.ISO_8859_1));

        ServletOutputStream outputStream=response.getOutputStream();
        byte[] bs=new byte[1024];
        while((input.read(bs)>0)){
            outputStream.write(bs);
        }
        outputStream.close();
        input.close();
    }

    /**
     *下载附件
     * @param sealId 印章Id
     */
    @RequestMapping(value="downLoadImg.do", method = RequestMethod.GET)
    public void downLoadImg(String sealId) throws IOException {

        Seal seal = sealService.findSealById(sealId);

        byte [] certByte = ESSGetBase64Decode(seal.getSealImg().getSealImgGifBase64());

        InputStream input = new ByteArrayInputStream(certByte);

        //设置MIME类型
        response.setContentType("application/octet-stream");
        //或者为response.setContentType("application/x-msdownload");
        //设置头信息,设置文件下载时的默认文件名，同时解决中文名乱码问题
        response.addHeader("Content-disposition", "attachment;filename="+new String("demo.png".getBytes(),
                StandardCharsets.ISO_8859_1));

        ServletOutputStream outputStream=response.getOutputStream();
        byte[] bs=new byte[1024];
        while((input.read(bs)>0)){
            outputStream.write(bs);
        }
        outputStream.close();
        input.close();
    }

    /**
     * 判断当前登录用户对某个系统是否有权限
     * 2018.05.24
     * @param isNeedCheckRange(1判断,0不判断)  是否需要判断范围,判断某个角色能否进入系统时,则不需要判断范围
     * @param powerId 权限Id
     * @param currentUnitId	当前点击的单位id,不需要传值时,传null即可
     */
    @RequestMapping(value="/check_auth.html", method = RequestMethod.POST)
    public void checkAuth(Integer isNeedCheckRange,String powerId,String currentUnitId){
        // 判断是否能进入某个系统时不需要判断范围
        if(isNeedCheckRange == 0){
            if(PowerUtil.checkUserIsHavaThisPower(session, powerId, roleAndPowerService, unitService,
                    Constant.topUnitLevel,Constant.companyLevel) ){
                FastJsonUtil.write_json(response, "{\"msg\":\""+"1"+"\"}");
            }else{
                FastJsonUtil.write_json(response, "{\"msg\":\""+"0"+"\"}");
            }
        }else{
            // 需要先判断管理范围再判断功能权限
            // 需要写入错误日志表
            if(currentUnitId == null){
//                errorLogService.addErrorLog("签章平台", "userController-checkAuth-获取到的currentUnitId为null");
                FastJsonUtil.write_json(response, "{\"msg\":\""+"2"+"\"}");
            }
            // 获取当前点击的单位对象
            Unit currentUnit = unitService.findUnitById(currentUnitId);
            // 需要写入错误日志表
            if(currentUnit == null){
//                errorLogService.addErrorLog("签章平台", "userController-checkAuth-获取到的单位对象为null");
                FastJsonUtil.write_json(response, "{\"msg\":\""+"2"+"\"}");
            }

            if(PowerUtil.checkUserIsHaveThisRangePower(session, currentUnit, Constant.topUnitLevel)){
                // 如果管理范围包含当前层级,则继续判断对应的功能
                if(PowerUtil.checkUserIsHavaThisPower(session, powerId, roleAndPowerService, unitService, Constant.topUnitLevel,
                        Constant.companyLevel) ){
                    FastJsonUtil.write_json(response, "{\"msg\":\""+"1"+"\"}");
                }else{
                    FastJsonUtil.write_json(response, "{\"msg\":\""+"0"+"\"}");
                }
            }else{
                // 如果管理范围不包含当前层级,则表示没有权限
                FastJsonUtil.write_json(response, "{\"msg\":\""+"0"+"\"}");
            }
        }
    }

}
